package com.yyfax.common.recyclerview.wrapper;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.yyfax.common.R;
import com.yyfax.common.recyclerview.adapter.MultiItemTypeAdapter;
import com.yyfax.common.recyclerview.base.EmptyViewDelagate;
import com.yyfax.common.recyclerview.base.ViewHolder;
import com.yyfax.common.recyclerview.view.IRecyclerView;
import com.yyfax.common.recyclerview.view.RefreshHeaderLayout;
import com.yyfax.common.toast.CompatToast;

import java.lang.ref.WeakReference;
import java.util.List;

/**
 * Created by aspsine on 16/3/12.
 * modified by fuqiang on 17/5/17
 * 在原有RecyclerView的基础上，添加下拉刷新和加载更多控件
 */
public class WrapperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    public static final int REFRESH_HEADER = Integer.MIN_VALUE;

    public static final int LOAD_MORE_FOOTER = Integer.MAX_VALUE;

    private StatesAdapter mStatesAdapter;
    private MultiItemTypeAdapter mAdapter;
    private IRecyclerView mRecyclerView;
    private WeakReference<Context> ctx;

    private final RefreshHeaderLayout mRefreshHeaderContainer;

    private final FrameLayout mLoadMoreFooterContainer;

    private RecyclerView.AdapterDataObserver mObserver = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            WrapperAdapter.this.notifyDataSetChanged();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            WrapperAdapter.this.notifyItemRangeChanged(positionStart + 1, itemCount);
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            WrapperAdapter.this.notifyItemRangeChanged(positionStart + 1, itemCount, payload);
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            WrapperAdapter.this.notifyItemRangeInserted(positionStart + 1, itemCount);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            WrapperAdapter.this.notifyItemRangeRemoved(positionStart + 1, itemCount);
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            WrapperAdapter.this.notifyDataSetChanged();
        }
    };

    public WrapperAdapter(@NonNull MultiItemTypeAdapter adapter, IRecyclerView recyclerView, Context context) {
        mStatesAdapter = new StatesAdapter(adapter, recyclerView);
        mAdapter = adapter;
        mRecyclerView = recyclerView;
        ctx = new WeakReference<>(context);
        mRefreshHeaderContainer = recyclerView.getRefreshHeaderContainer();
        mLoadMoreFooterContainer = recyclerView.getLoadMoreFooterContainer();
        mStatesAdapter.registerAdapterDataObserver(mObserver);
    }

    public WrapperAdapter(@NonNull MultiItemTypeAdapter adapter, IRecyclerView recyclerView, Context context, int emptyViewId, int errorViewId) {
        mStatesAdapter = new StatesAdapter(adapter, recyclerView);
        mAdapter = adapter;
        mRecyclerView = recyclerView;
        ctx = new WeakReference<>(context);
        mRefreshHeaderContainer = recyclerView.getRefreshHeaderContainer();
        mLoadMoreFooterContainer = recyclerView.getLoadMoreFooterContainer();
        mStatesAdapter.registerAdapterDataObserver(mObserver);
        mRecyclerView.getItemViewDelegateManager().addDelegate(StatesAdapter.STATE_EMPTY, new EmptyViewDelagate(emptyViewId));
        mRecyclerView.getItemViewDelegateManager().addDelegate(StatesAdapter.STATE_ERROR, new EmptyViewDelagate(errorViewId));
    }

    public RecyclerView.Adapter getAdapter() {
        return mAdapter;
    }

    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    WrapperAdapter wrapperAdapter = (WrapperAdapter) recyclerView.getAdapter();
                    if (isFullSpanType(wrapperAdapter.getItemViewType(position))) {
                        return gridLayoutManager.getSpanCount();
                    } else if (spanSizeLookup != null) {
                        return spanSizeLookup.getSpanSize(position - 1);
                    }
                    return 1;
                }
            });
        }
    }

    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        int position = holder.getAdapterPosition();
        int type = getItemViewType(position);
        if (isFullSpanType(type)) {
            ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
            if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
                StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) layoutParams;
                lp.setFullSpan(true);
            }
        }
    }

    private boolean isFullSpanType(int type) {
        return type == REFRESH_HEADER || type == LOAD_MORE_FOOTER;
    }

    @Override
    public int getItemCount() {
        return mStatesAdapter.getItemCount() + 2;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return REFRESH_HEADER;
        } else if (0 < position && position < mStatesAdapter.getItemCount() + 1) {
            return mStatesAdapter.getItemViewType(position - 1);
        } else if (position == mStatesAdapter.getItemCount() + 1) {
            return LOAD_MORE_FOOTER;
        }

        throw new IllegalArgumentException("Wrong type! Position = " + position);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == REFRESH_HEADER) {
            return ViewHolder.createViewHolder(parent.getContext(), mRefreshHeaderContainer);
        } else if (viewType == LOAD_MORE_FOOTER) {
            return ViewHolder.createViewHolder(parent.getContext(), mLoadMoreFooterContainer);
        } else {
            return mStatesAdapter.onCreateViewHolder(parent, viewType);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (0 < position && position < mStatesAdapter.getItemCount() + 1) {
            mStatesAdapter.onBindViewHolder(holder, position - 1);
        }
    }

    public void setRetryClickListener(StatesAdapter.RetryClickListener listener) {
        mStatesAdapter.setRetryClickListener(listener);
    }

    public void setState(@StatesAdapter.State int state) {
        mStatesAdapter.setState(state);
    }

    public int getCount() {
        return mAdapter.getItemCount();
    }

    public void refreshData(List list) {
        if (null != list && list.size() > 0) {
            mAdapter.removeAll();
            mAdapter.addData(list);
            setState(StatesAdapter.STATE_NORMAL);
            mRecyclerView.scrollToPosition(0);
        } else {
            setState(StatesAdapter.STATE_EMPTY);
        }
    }

    public void loadData(List list) {
        if (null == list || list.size() == 0) {
			if (ctx != null) {
				Context c = ctx.get();
				if (c == null) return;
				CompatToast.showShortToast(c.getApplicationContext(), R.string.has_no_more);
			}
        } else {
            mAdapter.addData(list);
            setState(StatesAdapter.STATE_NORMAL);
        }
    }

    public void setOnItemClickListener(MultiItemTypeAdapter.OnItemClickListener onItemClickListener){
        mAdapter.setOnItemClickListener(onItemClickListener);
    }
}
